package calbs.socket.server;

import calbs.socket.exception.AnalySocketException;
import calbs.socket.packaging.PackagingFactory;
import calbs.socket.pojo.req.ReqData;
import calbs.socket.pojo.resp.RespData;
import calbs.socket.server.cache.UserCache;
import calbs.socket.service.ServerService;
import calbs.socket.spring.SpringUtil;
import calbs.socket.tool.Byte2Hex;
import com.alibaba.fastjson.JSON;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by zhangqin on 2017-06-27.
 */
public class NettyServerHandler extends SimpleChannelInboundHandler<ReqData> {
    private static  final Logger logger = LoggerFactory.getLogger(NettyServerHandler.class);
    private ServerService serverService =SpringUtil.getBean(ServerService.class);
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        UserCache.remove(ctx.channel());
        ctx.close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        if(cause.getCause() instanceof AnalySocketException){
            AnalySocketException analySocketException = (AnalySocketException) cause.getCause();
            switch (analySocketException.getAnalySocketExceptionEmum()){
                case NO_FRAME:
                    logger.error(cause.getMessage(),cause);
                    ctx.flush();
                    break;
                case NO_FRAME_NOLGOIN:
                    logger.error(cause.getMessage(),cause);
                    UserCache.remove(ctx.channel());
                    ctx.close();
                    break;
                default:
                        logger.error(cause.getMessage(),cause);
                        UserCache.remove(ctx.channel());
                        ctx.close();
                        break;

            }
        }else{
            logger.error(cause.getMessage(),cause);
            UserCache.remove(ctx.channel());
            ctx.close();
        }

    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
            throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent e = (IdleStateEvent) evt;
            if (e.state() == IdleState.READER_IDLE) {
                logger.info("client has 30 second to read!");
                UserCache.remove(ctx.channel());
                ctx.close();
            } else if (e.state() == IdleState.WRITER_IDLE) {
                logger.info("server write fail");
            }
        }
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ReqData reqData) throws Exception {
        System.out.println(" client message"+ JSON.toJSONString(reqData.getBody()));
        RespData respData = serverService.getRespData(reqData);
        String s = PackagingFactory.bulidPackaging(respData.getBody().getFrameNumber()).analysisMsg(respData);
        byte[] bytes = Byte2Hex.HexString2Bytes(s);
        ByteBuf responseByteBuf = Unpooled.buffer(bytes.length);
        responseByteBuf.writeBytes(bytes);
        channelHandlerContext.writeAndFlush(responseByteBuf);
    }


}
